package net.apexes.wsonrpc.demo.server;

import net.apexes.wsonrpc.core.WebSocketSession;
import net.apexes.wsonrpc.core.WsonrpcConfig;
import net.apexes.wsonrpc.server.WsonrpcServer;
import net.apexes.wsonrpc.server.WsonrpcServerBase;
import org.glassfish.tyrus.core.MaxSessions;
import org.glassfish.tyrus.server.Server;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

/**
 * 
 * @author <a href=mailto:hedyn@foxmail.com>HeDYn</a>
 *
 */
public class TyrusDemoWsonrpcServerImpl extends AbstractDemoWsonrpcServer {

    private Server server;
    
    @Override
    public WsonrpcServer create(int port, String path, WsonrpcConfig config) {
        Map<String, Object> properties = new HashMap<>();
        properties.put("org.glassfish.tyrus.maxSessionsPerRemoteAddr", 10000);
        WsonrpcServerBase serverBase = new WsonrpcServerBase(config);
        TyrusJsr356Configuration.serverBase = serverBase;
        server = new Server("localhost", port, null, properties, TyrusJsr356Configuration.class);
        return serverBase;
    }

    @Override
    public void startup() throws Exception {
        server.start();
    }

    @Override
    public void shutdown() throws Exception {
        server.stop();
    }

    @MaxSessions(10000)
    @ServerEndpoint("/wsonrpc")
    public static class TyrusJsr356Configuration {

        static WsonrpcServerBase serverBase;

        @OnOpen
        public void onOpen(Session session) {
            serverBase.onOpen(new WebSocketSessionAdapter(session));
        }

        @OnClose
        public void onClose(Session session, CloseReason closeReason) {
            serverBase.onClose(session.getId());
        }

        @OnMessage
        public void onMessage(final Session session, final ByteBuffer buffer) {
            serverBase.onMessage(session.getId(), buffer);
        }
    }

    /**
     *
     * @author <a href=mailto:hedyn@foxmail.com>HeDYn</a>
     *
     */
    private static class WebSocketSessionAdapter implements WebSocketSession {

        private final Session session;

        private WebSocketSessionAdapter(Session session) {
            this.session = session;
        }

        @Override
        public String getId() {
            return session.getId();
        }

        @Override
        public boolean isOpen() {
            return session.isOpen();
        }

        @Override
        public void sendBinary(byte[] bytes) throws IOException {
            session.getBasicRemote().sendBinary(ByteBuffer.wrap(bytes));
        }

        @Override
        public void ping(byte[] bytes) throws IOException {
            session.getBasicRemote().sendPing(ByteBuffer.wrap(bytes));
        }

        @Override
        public void close() throws IOException {
            session.close();
        }

    }

}
